// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: MIT
package utils

import (
    "os"
    "sync"
    "time"
    "syscall"
    "os/signal"
    "github.com/sirupsen/logrus"
)

var (
    globalHandler *signalHandler
    globalMutex   sync.Mutex
    handlerStopped bool
)

type signalHandler struct {
    once     sync.Once
    callback func()
    stopChan chan struct{}
    sigc     chan os.Signal
    stopped  bool
    mutex    sync.Mutex
}

func HandleSignals(function func()) {
    globalMutex.Lock()
    defer globalMutex.Unlock()

    if globalHandler != nil {
        globalHandler.stop()
        time.Sleep(10 * time.Millisecond)
    }

    sigc := make(chan os.Signal, 1)
    signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)

    globalHandler = &signalHandler{
        callback: function,
        stopChan: make(chan struct{}),
        sigc:     sigc,
        stopped:  false,
    }

    globalHandler.start()
}

func (h *signalHandler) start() {
    go func() {
        defer func() {
            signal.Stop(h.sigc)
            close(h.sigc)
        }()

        for {
            select {
            case sig := <-h.sigc:
                h.mutex.Lock()
                if !h.stopped {
                    logrus.Infof("service received signal: %v", sig)
                    h.once.Do(h.callback)
                }
                h.mutex.Unlock()
            case <-h.stopChan:
                logrus.Debug("signal handler stopped normally")
                return
            }
        }
    }()
}

func (h *signalHandler) stop() {
    h.mutex.Lock()
    defer h.mutex.Unlock()

    if !h.stopped && h.stopChan != nil {
        h.stopped = true
        close(h.stopChan)
    }
}

func StopSignalHandlers() {
    globalMutex.Lock()
    defer globalMutex.Unlock()

    if globalHandler != nil {
        globalHandler.stop()
        globalHandler = nil
    }

    signal.Reset(syscall.SIGINT, syscall.SIGTERM)
}
